
package uk.ac.cam.cl.oscar;

import uk.ac.cam.cl.oscar.edgefinder.*;
import uk.ac.cam.cl.oscar.sift.*;
import java.sql.*;
import java.awt.image.BufferedImage;
import java.util.*;


public class ImageFinder {
    
    /** Returns a list of matching records
    		A single record if a distinct match
    		Three records if a lesser match
    		No records (array of zero size) if poor matches
    		
    		match[0] is always the best match.
    	*/
    public static Vector<ImageRecord> getMatches(BufferedImage image){
        
        Vector<ImageRecord> results = new Vector<ImageRecord>();
        
		try {
			EdgeFinder.extractRectangle (image);
                        BufferedImage cropped = image;
                        
                        // display the cropped image in the demo app
                        if(Demonstration.DemoAppInst != null){
                            Demonstration.DemoAppInst.displayNewCroppedImage("", cropped);
                        }
                        
			// cropped = ImageOperations.scale(cropped, cropped.getWidth() / 640.0);
                        Vector<Keypoint> kps = SIFT.findKeypoints (cropped);
                        
                        if(Demonstration.DemoAppInst != null){
                            Demonstration.DemoAppInst.displayNewKPImage(cropped, kps);
                        }
                        
			System.out.println ("Generated " + kps.size() + " keypoints for input image");
			
			DBAdaptor db = new DBAdaptor ();
			ResultSet rs = db.getAlgorithmHashes ("SIFT");
	
			int bestid = 0; double matchp = 10.0;
			int bestid2 = 0; double matchp2 = 0.0;
			int bestid3 = 0; double matchp3 = 0.0;
			int count = 0;
			while (rs.next()) {
				System.out.println ("Comparing " + count + " record to given image...");
				count++;
				Vector<Keypoint> kpdeserialised = 
					KeypointPacker.fromBinaryStream (rs.getBinaryStream("hash"));
				Vector<KeypointMatch> matches = 
					KeypointMatcher.findMatches(kps, kpdeserialised);

                                double dist = 0.0;
                                for (int i=0; i<matches.size(); i++) {
                                    dist += matches.elementAt(i).getDistance();
                                }
                                 dist /= (double)matches.size();
                                System.out.println("Dist: " + dist + " Matches: " + matches.size());
				double matchPercent = (double)matches.size() / ((double)kps.size()+ (double)kpdeserialised.size())/2.0;
					
				System.out.println ("Found " + Math.round(matchPercent*100) + "% matching keypoints");
				if (dist < matchp) {
					bestid3 = bestid2;
					matchp3 = matchp2;
					bestid2 = bestid;
					matchp2 = matchp;
					matchp = dist;
					bestid = rs.getInt ("id");
				}
			}
			
			/* If top result is differentiated by 90% */
			ImageRecord ir;
			if (count >= 1) {
				ir = DBAdaptor.getImageInfo(bestid);
				ir.setScore (matchp);
				results.add(ir);
			}
                        if (count >= 2 && (matchp * 0.9) <= matchp2) {
				ir = DBAdaptor.getImageInfo(bestid2);
				ir.setScore (matchp2);
				results.add(ir);
			}
			if (count >= 3 && (matchp * 0.9) <= matchp2) {
				ir = DBAdaptor.getImageInfo(bestid3);
				ir.setScore (matchp3);
				results.add(ir);
			}
			
		}
		catch (SQLException e) {
			e.printStackTrace();
		}
		
		return results;
    }
}
